package com.newcoretech.platform_service

import android.app.Activity
import android.graphics.Rect
import android.os.Build
import android.os.Handler
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AlphaAnimation
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import com.huawei.hms.hmsscankit.RemoteView
import com.huawei.hms.ml.scan.HmsScan
import com.newcoretech.platform_service.scanner.BeepManager
import com.newcoretech.platform_service.scanner.view.BarCodeUtil
import com.newcoretech.platform_service.scanner.view.ScanBoxView
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.platform.PlatformView

///
/// --author: xie jiayan
/// --created on: 2020-03-10 10:18
/// --description:
///
class QRScannerView(
    private val context: Activity,
    private val methodChannel: MethodChannel,
    id: Int,
    params: Map<String, Any>?,
    lifecycle: Lifecycle?
) :
    PlatformView,
    MethodChannel.MethodCallHandler,
    BaseLifecycleObserver {

    private var continueScan: Boolean = false
    private var rootView: View
    private var soundPoolUtil: BeepManager
    private var mRemoteView: RemoteView
    private var mScanBoxView: ScanBoxView? = null
    private var mBound = false
    private var mContainer: FrameLayout
    private var rect: Rect
    private var disposed = false

    companion object {
        const val TAG: String = "QRScannerView"
    }

    init {

        val height = params?.get("height") as Double
        val width = params["width"] as Double
        val wPx = dp2px(width.toInt())
        val hPx = dp2px(height.toInt())

        val screenWidth = context.resources.displayMetrics.widthPixels
        val screenHeight = context.resources.displayMetrics.heightPixels
        val rlp = FrameLayout.LayoutParams(screenWidth, screenHeight)
        rootView = LayoutInflater.from(context).inflate(R.layout.activity_camera_scan, null)
        mContainer = rootView.findViewById(R.id.container)
        continueScan = params["continueScan"] as Boolean
        mBound = params["bound"] as Boolean
        Log.w(TAG, "flutter input params: height=$height, width=$width, continueScan=$continueScan")

        val MAX_BOX_SIZE = BarCodeUtil.dp2px(context, 300f)

        val minSize = Math.min(screenHeight, screenWidth)
        val rectSize = (minSize * 4 / 5).coerceAtMost(MAX_BOX_SIZE)

        mScanBoxView = rootView.findViewById(R.id.scan_view_finder)
        initData()

        //methodChannel = MethodChannel(messenger, "scanner")
        methodChannel.setMethodCallHandler(this)

        if (!mBound) {
            var left = (screenWidth - rectSize) / 2
            var top = (screenHeight - rectSize) / 2
            left = left.coerceAtLeast(0)
            top = top.coerceAtLeast(0)
            rect = Rect(left, top, left + rectSize, top + rectSize)
        } else {
            val lp = mScanBoxView?.layoutParams
            lp?.width = wPx
            lp?.height = hPx
            mScanBoxView?.layoutParams = lp
            rect = Rect(0, 0, wPx, hPx)
        }
        soundPoolUtil = BeepManager(context)
        mRemoteView = RemoteView.Builder()
            .setContext(context).setBoundingBox(rect)
            .setContinuouslyScan(continueScan)
            .setFormat(HmsScan.ALL_SCAN_TYPE).build()
        Log.i(TAG, "[init] mRemoteView.onCreate")
        fixCameraPreviewRotation()
        mRemoteView.setOnResultCallback { scanRes ->
            scanRes?.let {
                if (it.isNotEmpty() && it.first() != null) {
                    soundPoolUtil.playBeepSoundAndVibrate()
                    val originalValue = it.first().originalValue
                    methodChannel?.invokeMethod("onScanResult", mapOf("result" to originalValue))
                    if (!continueScan) {
                        mRemoteView.pauseContinuouslyScan()
                    }
                }
            }
        }
        mRemoteView.onCreate(null)
        val lp = FrameLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT
        )
        mContainer.addView(mRemoteView, lp)
//        ScanUtil.startScan(context, 1, HmsScanAnalyzerOptions.Creator().create())
        lifecycle?.addObserver(this)
    }

    private fun fixCameraPreviewRotation() {
        Log.i(TAG, "build.Model:" + Build.MODEL)
        if (Build.MODEL == "ET40" || Build.MODEL == "ET40AA") {
            mRemoteView.rotation = 180f
        }
    }

    fun start() {
        Log.i(TAG, "start...........")
//        mContainer.removeAllViews()
//        val p = FrameLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
        val anim = AlphaAnimation(0f, 1f)
        anim.duration = 800
//        mContainer.addView(mRemoteView, p)
        mRemoteView.startAnimation(anim)

        Log.i(TAG, "[start] mRemoteView.onStart")
        mRemoteView.onStart()
        Log.i(TAG, "[start] mRemoteView.onResume")
        mRemoteView.onResume()
        Log.i(TAG, "[start] mRemoteView.resumeContinuouslyScan")
        mRemoteView.resumeContinuouslyScan()
//        ScanUtil.startScan(context, 1, HmsScanAnalyzerOptions.Creator().create())
    }

    fun stop() {
        Log.i(TAG, "stop...........")
        mRemoteView.pauseContinuouslyScan()
        mRemoteView.onPause()
        mRemoteView.onStop()
    }

    fun error(tag: String, message: String) {

    }

    private fun dp2px(dp: Int): Int = (dp * context.resources.displayMetrics.density).toInt()

    override fun getView(): View {
        Log.w(TAG, "getView")
        return rootView
    }

    private fun initData() {
        mScanBoxView?.apply {
            setMaskColor(getColor(R.color.mask_color))
            setCornerColor(getColor(R.color.corner))
            setBorderColor(getColor(R.color.box_line))
            setScanLineColor(
                arrayListOf(
                    getColor(R.color.scan_side),
                    getColor(R.color.scan_partial),
                    getColor(R.color.scan_middle)
                )
            )
            setFlashLightOffDrawable(R.drawable.ic_scanner_flashlight_off)
            setFlashLightOnDrawable(R.drawable.ic_scanner_flashlight_on)
            setFlashLightOffText(context.getString(R.string.czxing_click_close_flash_light))
            setFlashLightOnText(context.getString(R.string.czxing_click_open_flash_light))
//                invisibleFlashLightIcon()
            setDark(true)
            setScanBoxClickListener {
                return@setScanBoxClickListener mRemoteView.switchLight() ?: false
            }
        }
    }

    private fun getColor(colorRes: Int): Int {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            context.getColor(colorRes)
        } else {
            context.resources.getColor(colorRes)
        }
    }

    override fun onFlutterViewAttached(flutterView: View) {
        Log.i(TAG, "onFlutterViewAttached")
        super.onFlutterViewAttached(flutterView)
        //mRemoteView.onStart()
        start()
    }

    override fun onFlutterViewDetached() {
        super.onFlutterViewDetached()
        Log.i(TAG, "onFlutterViewDetached")
        stop()
    }

    override fun dispose() {
        Log.i(TAG, "dispose QRScanView = $this,mRemoteView=${mRemoteView}")
        if (disposed) return
        this.disposed = true
        //等待flutter 转场动画完成在执行资源释放操作
        Handler().postDelayed({
            mScanBoxView?.onDestroy()
            Log.i(TAG, "[dispose] mRemoteView.onStop")
            mRemoteView.onStop()
            Log.i(TAG, "[dispose] mRemoteView.onDestroy")
            mRemoteView.onDestroy()
            mScanBoxView = null

            soundPoolUtil.close()
        }, 400)

    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        Log.i(TAG, "ScannerView call method: ${call.method},methodCall=${methodChannel}")
        when (call.method) {
            "start" -> {
                if (!disposed) {
                    Log.i(TAG, "mRemoteView=${mRemoteView}")
                    start()
                }
                result.success(null)
            }
            "stop" -> {
                if (!disposed) {
                    stop()
                }
                result.success(null)
            }
            "pause" -> {
                if (!disposed) {
                    Log.i(TAG, "stop mRemoteView=${mRemoteView}")
                    mRemoteView.pauseContinuouslyScan()
                }
                result.success(null)
            }
            "resume" -> {
                if (!disposed) {
                    Log.i(TAG, "resume mRemoteView=${mRemoteView}")
                    mRemoteView.resumeContinuouslyScan()
                }
                result.success(null)
            }
            "dispose" -> {
                if (!disposed) {
                    dispose()
                }
                result.success(null)
            }
            else -> result.notImplemented()
        }
    }

    override fun onStart(owner: LifecycleOwner?) {
        Log.i(TAG, "onStart")
        if (disposed) return
        Log.i(TAG, "[onStart] mRemoteView.onStart")
        mRemoteView.onStart()
    }

    override fun onResume(owner: LifecycleOwner?) {
        Log.i(TAG, "onResume")
        if (disposed) return
        Log.i(TAG, "[onResume] mRemoteView.onResume")
        mRemoteView.onResume()
    }

    override fun onPause(owner: LifecycleOwner?) {
        Log.i(TAG, "onPause")
        if (disposed) return
        Log.i(TAG, "[onPause] mRemoteView.onPause")
        mRemoteView.onPause()
    }

    override fun onStop(owner: LifecycleOwner?) {
        Log.i(TAG, "onStop")
        if (disposed) return
        Log.i(TAG, "[onStop] mRemoteView.onStop")
        mRemoteView.onStop()
    }

    override fun onDestroy(owner: LifecycleOwner?) {
        Log.i(TAG, "onDestroy")
        if (disposed) return
        Log.i(TAG, "[onDestroy] mRemoteView.onDestroy")
        disposed = true;
        mScanBoxView?.onDestroy()
        mRemoteView.onDestroy()
        mScanBoxView = null;
        soundPoolUtil.close()
    }

}